#include "resultcurvechart.h"
#include "YuzhiLineEdit.h"
ResultCurveChart::ResultCurveChart(QGraphicsItem *parent)
    : QChart(parent)
{
    // 初始化
    ccView = nullptr;
    this->axisY = nullptr;

    previousPosMapY = 0;

    // 4条阈值线默认都未激活
    yuZhiActivate = "";

    // 默认鼠标不按下
    mousePressFlag = false;

    // 初始化单位长度
    yUnit = 0;

}

ResultCurveChart::~ResultCurveChart()
{
    ccView = nullptr;
    this->axisY = nullptr;
    qDeleteAll(seriesList.begin(), seriesList.end());
    seriesList.clear();
    yuZhiHash.clear();
}

void ResultCurveChart::init(QHash<QString, QSplineSeries*> seriesHash, CustomChartView *chartView){
    // 初始化图表序列
    this->seriesList = seriesHash;
    // 初始化图表和事件
    this->ccView = chartView;

    /* 计算鼠标坐标在图表上的映射的单位长度 */
    QAbstractAxis *absAxis = this->axes(Qt::Vertical).first(); // 获取图表坐标轴
    if(absAxis->type() == QAbstractAxis::AxisTypeValue){
        this->axisY = static_cast<QValueAxis*>(absAxis); // 转换为Value类型
    }

    // 检测坐标轴的值范围变化
    connect(this->axisY, &QValueAxis::rangeChanged, this, [=](qreal min, qreal max){
        // 计算y轴最大值
        this->yMax = max;
        this->updateMapUnit(); // 更新并重新计算映射单元和标签位置
    });
}

/* 更新映射计算单元 */
void ResultCurveChart::updateMapUnit(){
    this->yUnit = this->plotArea().height() / yMax; // 重新计算单位长度

    /* 更新渲染阈值标签位置 */
    QList<QString> yuZhiLabelKeys = yuZhiLabelHash.keys(); // 获取阈值标签key
    for(QString key : yuZhiLabelKeys){ // 设置阈值标签初始位置
        updateYuZhiLabelPos(yuZhiLabelHash[key], yuZhiHash[key]);
    }
}

/* 判断阈值线和鼠标之间的距离，小于最大距离，激活阈值线 */
void ResultCurveChart::activatedLine(double mouseY){
    if(yuZhiActivate != "" && mousePressFlag){ // 说明在拖动状态
        toggleLineStatus(nullptr, "");
        toggleLineStatus(seriesList[yuZhiActivate], lineColorHash[yuZhiActivate]);
        return;
    }

    /* 遍历阈值线，看看鼠标距离哪个阈值线近 */
    QList<QString> yuZhiKeys = this->yuZhiHash.keys();
    for(QString key : yuZhiKeys){
        if(abs(int(mouseY - this->yuZhiHash[key])) <= MAX_YDISTANCE){ // 距xx阈值线近
            yuZhiActivate = key;
            break;
        }else {
            yuZhiActivate = "";
        }
    }

    // 激活阈值线
    if(yuZhiActivate != ""){
        toggleLineStatus(seriesList[yuZhiActivate], this->lineColorHash[yuZhiActivate]);
    }else {
        toggleLineStatus(nullptr, QColor());
    }

    //    qDebug() << "yuZhiActivate" << yuZhiActivate;

}

/* 改变线的激活状态 */
void ResultCurveChart::toggleLineStatus(QSplineSeries* activateSeries, QColor lineColor){
    if(activateSeries != nullptr){ // 判空操作
        activateSeries->setPen(QPen(lineColor, ACTIVATE_LINE_THICKNESS)); // 改变曲线粗细
    }else { // 未激活状态
        QList<QString> sListKeys = seriesList.keys();
        for (QString key : sListKeys) {
            seriesList[key]->setPen(QPen(lineColorHash[key])); // 改变曲线粗细
        }
    }
    this->update(); // 页面刷新
}

/* 获取阈值线值和颜色 */
void ResultCurveChart::setSeriesInfo(QHash<QString, double> yuZhi, QHash<QString, QColor> lineColor, QHash<QString, YuzhiLineEdit*> yuZhiLabel, QList<QString> validYuZhi){
    this->lineColorHash = lineColor; // 写入颜色
    this->yuZhiLabelHash = yuZhiLabel; // 写入阈值标签

    LOG << "VAlIDvalidYuZhi" << validYuZhi << yuZhi;

    /* 遍历合法阈值列表，将合法阈值加入到阈值列表中 */
    for(const QString validYZ : validYuZhi){
        this->yuZhiHash.insert(validYZ, yuZhi[validYZ]);
    }

    this->updateMapUnit(); /* 更新单元长度和标签位置 */
}

/* 更新阈值标签位置 */
void ResultCurveChart::updateYuZhiLabelPos(YuzhiLineEdit *yuZhiLabel, double mapPos){
    // 宽高
    int width = yuZhiLabel->size().width();
    int height = yuZhiLabel->size().height();
    // 水平垂直距离
    double hPos = this->plotArea().x();
    // 将Y轴映射改变回坐标形式
    double vPos = (yMax - mapPos) * yUnit + this->plotArea().y() - height; // 减去标签高度，让其在线的上方

//    LOG << "幽州最大值改变" << this->yMax << mapPos << vPos;

    /* 边界控制 */
    /* 判断，线的位置与图表上边界的距离 */
    if(vPos < (height * 1.5)){ // 如果图标的位置距图表上边界的距离小1.5个标签高度，则标签位置改到线的下方
        vPos += height;
    }
    // 渲染标签位置
    yuZhiLabel->setGeometry(static_cast<int>(hPos), static_cast<int>(vPos), width, height);
    // 更改标签值
    yuZhiLabel->setText(QString::number(mapPos, 'f', 2));
    /* 双击编辑阈值 */
    connect(yuZhiLabel, &YuzhiLineEdit::doubleClicked, yuZhiLabel, &YuzhiLineEdit::setReadOnly);
    // 自适应大小
    yuZhiLabel->adjustSize();

//    LOG << "LABLEPOS" << yuZhiLabel->geometry();

    // 更新页面
    this->update();
}

/* 初始化移动事件 */
void ResultCurveChart::initMoveEvent(QMouseEvent *){
    mousePressFlag = true; // 鼠标按下标识位更新
    this->yUnit = this->plotArea().height() / yMax; // 计算单位长度
}

/* 控制阈值线移动 */
void ResultCurveChart::handleLineMove(QMouseEvent *event){
    /* 当前鼠标所在位置的坐标与y轴的值的映射关系 */
    double yMap = yMax - (event->y() - this->plotArea().y()) / yUnit; // y映射值 = y轴最大值 - 当前鼠标坐标在Chart上的坐标 / 单位长度

    activatedLine(yMap); // 激活阈值线
    if(this->mousePressFlag && yuZhiActivate != ""){ // 鼠标按下，阈值线激活并可拖动
        QSplineSeries* activateSeries = seriesList[yuZhiActivate]; // 记录激活的阈值线
        double deltaPos = yMap - previousPosMapY; // 记录鼠标移动的距离
        QVector<QPointF> seriesPoints = activateSeries->pointsVector(); // 记录当前系列所有点坐标
        QVector<QPointF> newSeriesPoints; // 记录当前系列所有点新坐标
        QVector<QPointF>::iterator it; // 迭代器

        // 更新点数据
        for(it = seriesPoints.begin(); it != seriesPoints.end(); it++){
            double pointDelta = (*it).y() + deltaPos; // 新坐标
            /* 边界控制 */
            if(event->y() > this->plotArea().y() + this->plotArea().height()){ // 鼠标位置出上界
                pointDelta = 0; // 线坐标最大
            }else if(event->y() < this->plotArea().y()){ // 鼠标位置出下界
                pointDelta = yMax; // 线坐标最小
            }
            /* 写入新坐标 */
            QPointF newPos((*it).x(), pointDelta);
            newSeriesPoints.append(newPos);
        }
        // 更新点坐标
        activateSeries->replace(newSeriesPoints);
        // 更新阈值
        this->yuZhiHash[yuZhiActivate] = newSeriesPoints.begin()->y();

//        LOG << "this->yuZhiHash[yuZhiActivate]" << this->yuZhiHash[yuZhiActivate];

        // 更新标签位置
        if(yuZhiActivate != ""){
            updateYuZhiLabelPos(yuZhiLabelHash[yuZhiActivate], this->yuZhiHash[yuZhiActivate]);
        }
        this->update(); // 页面刷新
    }else {} // 鼠标未按下，阈值线不会被拖动，但可以被激活
    // 更新鼠标位置信息
    this->previousPosMapY = yMap;
}

/* 移动事件结束，进行后续处理 */
void ResultCurveChart::finishMoveEvent(QMouseEvent *){
    mousePressFlag = false; // 鼠标按下标识位更新
//    QList<QString> keys = yuZhiLabelHash.keys();
    /* 迭代器判断yuzhilineedit是否被选中 */
    int count = 0;
    QHash<QString, YuzhiLineEdit *>::iterator yuzhiHash;
    for (yuzhiHash = yuZhiLabelHash.begin(); yuzhiHash != yuZhiLabelHash.end(); yuzhiHash++){
        if (!yuzhiHash.value()->hasFocus()){
            count++;
        }
    }
    if(count == yuZhiLabelHash.size())
    {
        LOG << yuZhiHash;
        emit ResultCurveChart::updateYuZhi(yuZhiHash); // 发送信号，更新阈值
    }
}

/* 窗口大小改变 */
void ResultCurveChart::widgetResizeEvent(QResizeEvent *){
    this->yUnit = this->plotArea().height() / yMax; // 重新计算单位长度
    /* 初始化渲染阈值标签位置 */
    QList<QString> yuZhiLabelKeys = yuZhiLabelHash.keys(); // 获取阈值标签key
    for(const QString key : yuZhiLabelKeys){ // 设置阈值标签初始位置
        updateYuZhiLabelPos(yuZhiLabelHash[key], yuZhiHash[key]);
    }
}

/* 解绑鼠标按下事件 */
void ResultCurveChart::disconnectPressEvent(){
    if(this->ccView != nullptr){
        disconnect(ccView, &CustomChartView::chartViewMousePress, this, &ResultCurveChart::initMoveEvent);
    }
}
/* 解绑鼠标移动事件 */
void ResultCurveChart::disconnectMoveEvent(){
    if(this->ccView != nullptr){
        disconnect(ccView, &CustomChartView::chartViewMouseMove, this, &ResultCurveChart::handleLineMove);
    }
}
/* 解绑鼠标释放事件 */
void ResultCurveChart::disconnectReleaseEvent(){
    if(this->ccView != nullptr){
        disconnect(ccView, &CustomChartView::chartViewMouseRelease, this, &ResultCurveChart::finishMoveEvent);
    }
}
/* 解绑鼠标双击事件 */
void ResultCurveChart::disconnectDoubleClickEvent() {
    if(this->ccView != nullptr){
        disconnect(ccView, &CustomChartView::chartViewDoubleClick, this, &ResultCurveChart::determineDClickPos);
    }
}
/* 解绑窗口变化事件 */
void ResultCurveChart::disconnectChangeEvent() {
    if(this->ccView != nullptr){
        disconnect(ccView,&CustomChartView::chartViewResize, this , &ResultCurveChart::widgetResizeEvent);
    }
}
/* 绑定鼠标按下事件 */
void ResultCurveChart::connectPressEvent(){
    if(this->ccView != nullptr){
        connect(ccView, &CustomChartView::chartViewMousePress, this, &ResultCurveChart::initMoveEvent);
    }
}
/* 绑定鼠标移动事件 */
void ResultCurveChart::connectMoveEvent(){
    if(this->ccView != nullptr){
        connect(ccView, &CustomChartView::chartViewMouseMove, this, &ResultCurveChart::handleLineMove);
    }
}
/* 绑定鼠标释放事件 */
void ResultCurveChart::connectReleaseEvent(){
    if(this->ccView != nullptr){
        connect(ccView, &CustomChartView::chartViewMouseRelease, this, &ResultCurveChart::finishMoveEvent);
    }
}
/* 绑定双击阈值线编辑 */
void ResultCurveChart::connectDoubleClickEvent() {
    if(this->ccView != nullptr){
        connect(ccView, &CustomChartView::chartViewDoubleClick, this, &ResultCurveChart::determineDClickPos);
    }
}
void ResultCurveChart::connectChangeEvent() {
    if(this->ccView != nullptr){
        connect(ccView,&CustomChartView::chartViewResize, this , &ResultCurveChart::widgetResizeEvent);
    }
}




/* 清除函数 */
void ResultCurveChart::clear(){
    // 清除阈值标签
    if(this->yuZhiLabelHash.size() != 0){
        qDeleteAll(this->yuZhiLabelHash.begin(), this->yuZhiLabelHash.end());
        this->yuZhiLabelHash.clear();
    }
    // 清空数组
    if(this->validYuZhi.size() != 0){
        this->validYuZhi.clear(); // 合法阈值
    }
    // 清空阈值数组
    if(this->yuZhiHash.size() != 0){
        this->yuZhiHash.clear();
    }
    // 清空chart页面合法阈值列表
    this->validYuZhi.clear();
    // 清空序列中的点
    for(QSplineSeries* value : seriesList.values()){
        value->clear();
    }
    this->update(); // 图表更新
}




void ResultCurveChart::determineDClickPos(QMouseEvent *event) {
    /* 当前鼠标所在位置的坐标与y轴的值的映射关系 */
    double yMap = yMax - (event->y() - this->plotArea().y()) / yUnit; // y映射值 = y轴最大值 - 当前鼠标坐标在Chart上的坐标 / 单位长度
    QList<QString> yuZhiKeys = this->yuZhiHash.keys();
    for(QString key : yuZhiKeys){
        if(abs(int(yMap - this->yuZhiHash[key])) <= MAX_YDISTANCE){ // 距xx阈值线近
            yuZhiActivate = key;
            break;
        }else {
            yuZhiActivate = "none";
        }
    }
    LOG << "bianji";
    LOG << "KKKKKK" << yuZhiActivate;
    emit ResultCurveChart::returnYuzhiHash(yuZhiActivate);
}





